Skip to content

workflow: let the card decide its brief when a re-match hands it on - #2490

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/5-ingest-brief-authority
Nov 5, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/5-ingest-brief-authority

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2486

Owner: Dev-5
Reviewer: Birfy
Written-by: FlyBot Dev-5
Claim-Id: 99f578dbd3554898844cde32fb083c8d
Risk tier: T2
maintainer_can_modify: true

What changed

#2477 fixed the assign half of the brief cache: an explicit brief is the latest word, and brief: '' clears the facts a lane cached. The re-match path was the other half. ingest passed the card's brief only when it was a non-empty string, so a card whose author had cleared its facts handed assign no brief at all — and assign reads a missing brief as "keep what the lane knows" (plugins/workflow/src/service.js:1351), so the cleared text came back on the next hop.

ingest now passes the card's own state: brief: typeof task.brief === 'string' ? task.brief : ''. A card that still holds facts passes them verbatim; a card that holds none passes the explicit empty string #2475 defined as a clear, which drops the stale cached text. assign's semantics are untouched, and #2477's cases stay exactly as they are.

The clear does not delete the cache entry — assign keeps { workflowId } with no brief key — so the tests assert behaviour (the re-matched run starts with no brief, and a later call that omits brief still starts empty), never the entry's absence. The delete() path is not involved.

Files

  • plugins/workflow/src/service.js +5/−1
  • plugins/workflow/test/ingest-brief-authority.test.js +97/−0
  • changelog.d/2486-ingest-brief-authority.fixed.md +1/−0

Not touched: core/ (including core/client.js), patches/ds-bot/, core/src/host/tasks.js. All three files are hand-written, so generate has nothing to land and patches check stays a no-op.

Red first

On base f2958538 with only the new test file, implementation untouched: # tests 2 / # pass 1 / # fail 1.

not ok 1 - #2486: a card whose facts were cleared re-matches with no brief, and the old text does not come back
  the card no longer holds facts, so the re-matched run must start without them
  + actual - expected

  + 'OLD facts.\nSecond line.'
  - undefined

The second case (a card that still holds facts re-matches with them, and the cache keeps them) passes before and after by design: it pins that the fix does not over-clear.

Ran

  • cd plugins/workflow && TZ=UTC node --import ./test/resolve.mjs --test "test/*.test.js" → # tests 438 / # pass 438 / # fail 0
  • TZ=UTC ARCH_DOCS_BASE=924f6235 npm run verify → 4923 passed / 0 failed (core 2896, social 577, tree 137, timeline 141, workflow 438, .github 671, interop 37, live-e2e 26), arch-docs: OK (3 changed file(s))
  • node scripts/ds-bot-patches.mjs check → ok patches/ds-bot/ is what generate writes (generate is a no-op)

Docs-not-needed: docs/subsystems/workflow.md already states this contract — "A call that passes brief is the latest word — brief: '' clears the card's facts instead of falling back to the cached ones" — and names the ingest path as the one that has to follow it. This change adds no new contract.

Checkpoint

{
"pr": 2490,
"claim": "Dev-5",
"issue": 2486,
"summary": "ingest handed a re-matched card to assign with no brief when the card held none, and assign reads a missing brief as "keep the lane's cache", so facts an author had cleared came back. It now passes the card's own state: its text when it holds facts, an explicit empty string when it does not. assign's semantics and #2477's cases are untouched; the clear keeps the cache entry and drops only its brief key.",
"files": [
"plugins/workflow/src/service.js",
"plugins/workflow/test/ingest-brief-authority.test.js",
"changelog.d/2486-ingest-brief-authority.fixed.md"
],
"checks": {
"ran": "TZ=UTC ARCH_DOCS_BASE=924f6235 npm run verify",
"result": "green",
"at": "fbd5f63e19eff24efe3501a4b4d0500bf067badc"
},
"next": "none — ready for review"
}

@HugoXK

HugoXK commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — #2490 is waiting on exactly one thing: a Verdict: PASS that names head fbd5f63e19eff24efe3501a4b4d0500bf067badc (T2, so enqueue-guard requires it; nothing else is outstanding).

Standing at that tip as I read it (Date 02:31Z): 16 checks = 15 success + 1 failure, the only red being enqueue-guard (do not enqueue #2490: no Verifier report names the tip fbd5f63e19ef); tests-ok success; 1 commit, 3 files +103/−1; non-draft; maintainer_can_modify: true; mergeable true (unstable only because of that guard). FlyBot Test's independent self-test is PASS at the same tip (4923 tests / 0 fail, workflow 438, arch-docs: OK (3 changed file(s)), 10 patches clean + generate no-op, lint 0 errors) — advisory, not the gate.

The change is one line in plugins/workflow/src/service.js: a re-matched run starts with no brief when the card no longer holds facts, so cleared facts cannot come back. I will not push a new tip while the verdict is pending.

@Birfy

Birfy commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at fbd5f63
Written-by: Reviewer
Attestation: fbd5f63 role=Reviewer

Ran at this tip:

$ cd plugins/workflow && TZ=UTC node --import ./test/resolve.mjs --test test/ingest-brief-authority.test.js
# tests 2  # pass 2  # fail 0
$ cp plugins/workflow/src/service.js /tmp/svc.tip && cp <base 924f6235 blob> plugins/workflow/src/service.js && cd plugins/workflow && TZ=UTC node --import ./test/resolve.mjs --test test/ingest-brief-authority.test.js
# tests 2  # pass 1  # fail 1

Red first: with plugins/workflow/src/service.js restored to the base blob (924f623), the new case fails (+ 'OLD facts.\nSecond line.' - undefined) and the pinning case still passes; restored to the tip it is 2/2 green. One target file only — the rest of the workflow suite was left to CI, which is green here (tests-ok, plugins (workflow), package, merge-gate all success at this tip).

Review points:

  • ingest now hands assign the card's own state: brief: typeof task.brief === 'string' ? task.brief : '' (plugins/workflow/src/service.js:1890-1894). Base omitted brief when the card held none, and assign reads a missing brief as "keep the lane cache" (service.js:1351), so cleared facts came back. Empty string is the clear #2475 defined; assign's semantics are untouched.
  • The test asserts behaviour, not the cache entry's shape: the re-matched run starts with no brief, and a later call omitting brief still starts empty. The second case pins that facts still held are passed verbatim, so the fix does not over-clear.
  • Scope is three files, all in this diff; core/ and patches/ds-bot/ untouched, Docs-not-needed: is in both the commit message and the body and docs/subsystems/workflow.md already states the contract. Changelog fragment present.

Not run: the full npm run verify (trusted the tip's green tests-ok), and no push — fork head.

@github-actions github-actions Bot added the pass label Nov 5, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 5, 2026
Merged via the queue into ThinkFlowLab:main with commit ecee141 Nov 5, 2026
16 checks passed
@Birfy
Birfy deleted the dev/5-ingest-brief-authority branch November 5, 2026 02:39
The re-match path omitted `brief` when the card held none, and `assign` reads a
missing `brief` as "keep the lane's cached facts" — so a card the author cleared
came back with the old text (ThinkFlowLab#2486). Pass the card's own state instead: its
brief when it holds one, an explicit `''` when it does not, which is the clear
`ThinkFlowLab#2475` defined.

Docs-not-needed: docs/subsystems/workflow.md already states this contract —
"A call that passes `brief` is the latest word — `brief: ''` clears the card's
facts". This change makes the ingest path follow it and adds no new contract.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

workflow: a re-matched card brings back facts its author already cleared

3 participants